#include "DoOpBoolean.h"
#include "DevilSemantic.h"

void DoOpBoolean::ds_eq::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;

	bool b = true;
	if (!DoOpBoolean::canGreatOrLess(obj1, obj2))
		CXXTHROW;
	b = obj2->equals(obj1);
	state.getOpStack().push(newBool(b));
}

void DoOpBoolean::ds_ne::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	bool result = true;
	if (obj1->type() != obj2->type()) {
		result = false;
	} else {
		result = obj1->equals(obj2);
	}
	
	state.getOpStack().push(newBool(!result));
}

void DoOpBoolean::ds_ge::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	bool b = true;
	if (!DoOpBoolean::canGreatOrLess(obj1, obj2))
		CXXTHROW;
	if (obj1->type() == eNumber) {
		b = (toNumber(obj2))->compare(toNumber(obj1)) >= 0;
	} else if (obj1->type() == eString){
		b = (toString(obj2))->compare(toString(obj1)) >= 0;
	} else {
		CXXTHROW;
	}
	
	state.getOpStack().push(newBool(b));
}

void DoOpBoolean::ds_gt::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	bool b = true;
	if (!DoOpBoolean::canGreatOrLess(obj1, obj2))
		CXXTHROW;
	if (obj1->type() == eNumber) {
		b = (toNumber(obj2))->compare(toNumber(obj1)) > 0;
	} else if (obj1->type() == eString){
		b = (toString(obj2))->compare(toString(obj1)) > 0;
	} else {
		CXXTHROW;
	}
	
	state.getOpStack().push(newBool(b));
}

void DoOpBoolean::ds_le::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	bool b = true;
	if (!DoOpBoolean::canGreatOrLess(obj1, obj2))
		CXXTHROW;
	if (obj1->type() == eNumber) {
		b = (toNumber(obj2))->compare(toNumber(obj1)) <= 0;
	} else if (obj1->type() == eString){
		b = (toString(obj2))->compare(toString(obj1)) <= 0;
	} else {
		CXXTHROW;
	}
	
	state.getOpStack().push(newBool(b));
}

void DoOpBoolean::ds_lt::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	bool b = true;
	if (!DoOpBoolean::canGreatOrLess(obj1, obj2))
		CXXTHROW;
	if (obj1->type() == eNumber) {
		b = (toNumber(obj2))->compare(toNumber(obj1)) < 0;
	} else if (obj1->type() == eString){
		b = (toString(obj2))->compare(toString(obj1)) < 0;
	} else {
		CXXTHROW;
	}
	
	state.getOpStack().push(newBool(b));
}

void DoOpBoolean::ds_and::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	if (obj1->type() == eNumber && obj2->type() == eNumber) {
		int x = toNumber(obj2)->getInt();
		int y = toNumber(obj1)->getInt();
		
		state.getOpStack().push(newNumber(x & y));
	} else if (obj1->type() == eBoolean && obj2->type() == eBoolean) {
		bool x = toBool(obj2)->getBool();
		bool y = toBool(obj1)->getBool();
		
		state.getOpStack().push(newBool(x && y));
	} else {
		CXXTHROW
	}
}

void DoOpBoolean::ds_not::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	switch (obj1->type()) {
		case eBoolean:
			state.getOpStack().push(newBool(!toBoolean(obj1)->getBool()));
			break;
		case eNumber:
			{
				DoNumber *num = toNumber(obj1);
				if (num->getType() == DoNumber::eReal)
					CXXTHROW
				state.getDictStack().push(newNumber(~num->getInt()));
			}
			break;
		default:
			CXXTHROW
	}
}

void DoOpBoolean::ds_or::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	if (obj1->type() == eNumber && obj2->type() == eNumber) {
		int x = toNumber(obj2)->getInt();
		int y = toNumber(obj1)->getInt();
		
		state.getOpStack().push(newNumber(x | y));
	} else if (obj1->type() == eBoolean && obj2->type() == eBoolean) {
		bool x = toBool(obj2)->getBool();
		bool y = toBool(obj1)->getBool();
		
		state.getOpStack().push(newBool(x || y));
	} else {
		CXXTHROW
	}
}

void DoOpBoolean::ds_xor::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	if (obj1->type() == eNumber && obj2->type() == eNumber) {
		int x = toNumber(obj2)->getInt();
		int y = toNumber(obj1)->getInt();
		
		state.getOpStack().push(newNumber(x ^ y));
	} else if (obj1->type() == eBoolean && obj2->type() == eBoolean) {
		bool x = toBool(obj2)->getBool();
		bool y = toBool(obj1)->getBool();
		
		state.getOpStack().push(newBool(x ^ y));
	} else {
		CXXTHROW
	}
}

void DoOpBoolean::ds_true::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	state.getOpStack().push(newBool(true));
}

void DoOpBoolean::ds_false::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1;
	CRefPtr< _DoObject > obj2;
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	state.getOpStack().push(newBool(false));
}

void DoOpBoolean::ds_bitshift::execute(DevilSemantic &state)
{
	CRefPtr< _DoObject > obj1 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj2 = state.getOpStack().pop();
	CRefPtr< _DoObject > obj3;
	CRefPtr< _DoObject > obj4;
	CRefPtr< _DoObject > obj5;
	
	int x = toNumber(obj2)->getInt();
	int y = toNumber(obj1)->getInt();
	state.getOpStack().push(newNumber(x >> y));
}

